#include "tcp_server.h"
#include "server_handle.h"
#include "client_handle.h"
#include "epoll_reactor.h"
#include <cassert>
#include <signal.h>
#include <sys/epoll.h>

using namespace std;

TcpServer::TcpServer(ITcpEvent* event, time_t timeout)
: mTcpEvent(event)
, mTimeout(timeout)
, mLastTime(time(nullptr))
, mServer(new ServerHandle(this)) {
    assert(event != nullptr);
}

TcpServer::~TcpServer() {
    mEpoll.RemoveHandle(mServer);
    delete mServer;
    mServer = nullptr;
    for (auto it : mClients) {
        delete it.first;
    }
    mClients.clear();
}

tuple<bool, string> TcpServer::Init(const std::string& ip, int port, int backlog) {
    signal(SIGPIPE, SIG_IGN);
    auto ret = mServer->Init(ip, port, backlog);
    if (get<0>(ret)) {
        mEpoll.RegisterHandle(mServer, EPOLLET | EPOLLIN);
    }
    return ret;
}

void TcpServer::HandleEvents(time_t timeout) {
    mEpoll.HandleEvents(timeout * 1000);
    //每隔一段时间处理超时和已断开链接的句柄
    time_t now = time(nullptr);
    if (now - mLastTime < mTimeout)
        return;
    //超时处理
    unique_lock<shared_mutex> lock(mMutex);
    for (auto it = mClients.begin(); it != mClients.end();) {
        if (time(nullptr) - it->second >= mTimeout) {
            it->first->Close("timeout");
        }
        if (it->first->IsClose()) {
            delete it->first;
            it = mClients.erase(it);
        } else {
            ++it;
        }
    }
    mLastTime = now;
}

void TcpServer::Write(IHandle* h, const char* buf, int len) {
    shared_lock<shared_mutex> lock(mMutex);
    auto it = mClients.find(dynamic_cast<ClientHandle*>(h));
    if (it != mClients.end()) {
        it->first->Write(buf, len);
    }
}

void TcpServer::Close(IHandle* h) {
    shared_lock<shared_mutex> lock(mMutex);
    auto it = mClients.find(dynamic_cast<ClientHandle*>(h));
    if (it != mClients.end()) {
        it->first->Close("close");
    }
}

void TcpServer::OnConnect(IHandle* h) {
    //存储句柄
    {
        unique_lock<shared_mutex> lock(mMutex);
        mClients[dynamic_cast<ClientHandle*>(h)] = time(nullptr);
    }
    //注册到 Epoll
    mEpoll.RegisterHandle(h, EPOLLET | EPOLLIN | EPOLLOUT);
    //通知外部有新的链接
    mTcpEvent->OnConnect(*this, h);
}

void TcpServer::OnRead(IHandle* h, const char* buf, int len) {
    //更新时间
    {
        shared_lock<shared_mutex> lock(mMutex);
        auto it = mClients.find(dynamic_cast<ClientHandle*>(h));
        if (it != mClients.end()) {
            it->second = time(nullptr);
        }
    }
    //回调给外部处理
    mTcpEvent->OnRead(*this, h, buf, len);
}

void TcpServer::OnDisconnect(IHandle* h) {
    //从 Epoll 删除
    mEpoll.RemoveHandle(h);
    //通知外部链接已关闭
    mTcpEvent->OnDisconnect(*this, h);
}

void TcpServer::OnLog(IHandle* h, const string& log) {
    if (h != nullptr) {
        mTcpEvent->OnClientLog(*this, h, log);
    } else {
        mTcpEvent->OnServerLog(*this, log);
    }
}
